﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using Brain;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using Brain.Editor;
using Timer = System.Windows.Forms.Timer;
using Brain.Rendering;

namespace Brain.Windows
{
    public partial class XnaViewControl : GraphicsDeviceControl
    {
        /// <summary>
        /// Timer used for updating and drawing the Engine
        /// </summary>
        public Timer Timer { get; set; }

        public Stopwatch ElapsedTime { get; set; }
        public Stopwatch TotalTime { get; set; }

        public GameTime GameTime { get; set; }

        public event SetVoid OnDraw;

        public IPickingManager2D PickingManager2D;
        public IPickingManager3D PickingManager3D;

        public DummyGame Game;

        public XnaViewControl()
        {
            ElapsedTime = new Stopwatch();
            TotalTime = new Stopwatch();

            TotalTime.Start();
        }

        public event SetVoid OnStart;

        protected override void Initialize()
        {
            Timer = new System.Windows.Forms.Timer();
            Timer.Interval = (int)((1f / 60f) * 1000);
            Timer.Tick += new EventHandler(Timer_Tick);

            Mouse.WindowHandle = Handle;

            base.Initialize();

            Timer.Start();

            Engine.InitializeEngineWithDefaultManagers(this.Service);
            Engine.Instance.RunningEditor = true;

            EditorSceneData sceneData = new EditorSceneData();
            Engine.Instance.SerializationManager.SceneData = sceneData;

            Game = new DummyGame();
            Engine.Instance.AssignGame(Game);

            PickingManager2D = new DefaultPickingManager2D(this);
            PickingManager3D = new PickingManager3D_Color();

            Engine.Instance.AddManager(new DefaultRenderManager2D(this.Service.GraphicsDevice));
            Engine.Instance.AddManager(new DefaultRenderManager3D(this.Service.GraphicsDevice));

            GameScreen screen = new GameScreen();

            InputFreeCamera3D Camera = new InputFreeCamera3D(screen);
            Camera.GetAspectRatioFromEngineViewport = true;
            Camera.ShouldSerialize = false;
            Engine.Instance.CameraManager.Camera3D = Camera;

            if (OnStart != null)
            {
                OnStart();
            }
        }

        public void NewLevel()
        {
            if (Engine.Instance != null)
            {
                Engine.EndAndDispose();
            }

            Engine.InitializeEngineWithDefaultManagers(this.Service);
            Engine.Instance.RunningEditor = true;

            EditorSceneData sceneData = new EditorSceneData();
            Engine.Instance.SerializationManager.SceneData = sceneData;

            Game = new DummyGame();
            Engine.Instance.AssignGame(Game);

            PickingManager2D = new DefaultPickingManager2D(this);
            PickingManager3D = new PickingManager3D_Color();

            Engine.Instance.AddManager(new DefaultRenderManager2D(this.Service.GraphicsDevice));
            Engine.Instance.AddManager(new DefaultRenderManager3D(this.Service.GraphicsDevice));

            GameScreen screen = new GameScreen();

            InputFreeCamera3D Camera = new InputFreeCamera3D(screen);
            Camera.GetAspectRatioFromEngineViewport = true;
            Camera.ShouldSerialize = false;
            Engine.Instance.CameraManager.Camera3D = Camera;

            WorldObject.LockMaxRotationTo2Pi = true;

            if (OnStart != null)
            {
                OnStart();
            }
        }


        protected void Timer_Tick(object sender, EventArgs e)
        {
            // Invalidate everything so the whole control refreshes
            this.Invalidate();

            // Force the view update
            this.Update();
        }

        protected override void Draw()
        {
            if (Engine.Instance != null)
            {
                if (PickingManager3D != null)
                {
                    if (PickingManager3D.ShouldUpdate)
                    {
                        PickingManager3D.Update();
                    }
                    if (PickingManager3D.ShouldDraw)
                    {
                        PickingManager3D.Draw();
                    }
                }

                Game.UpdateDraw(GameTime);

                Mouse.WindowHandle = this.Handle;


                UpdateGameTime();
                Engine.Instance.Update(GameTime);

                UpdateGameTime();
                Engine.Instance.Draw(GameTime);
                if (OnDraw != null)
                {
                    OnDraw();
                }


                if (PickingManager2D != null &&
                    PickingManager2D.ShouldUpdate)
                {
                    PickingManager2D.Update();
                }


                if (PickingManager3D != null)
                {
                    PickingManager3D.EndDraw();
                }
                if (Engine.Instance.EditorManager != null)
                {
                    Engine.Instance.EditorManager.OnDraw(PickingManager2D, PickingManager3D);
                }
            }
            
        }

        protected void UpdateGameTime()
        {
            // Recreate the GameTime with the current values
            GameTime = new GameTime(TotalTime.Elapsed, ElapsedTime.Elapsed);

            ElapsedTime.Reset();
            ElapsedTime.Start();
        }
    }
}
